/**
 * 
 */
package com.antilia.infomaresme.data.dao.impl;

import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;

import com.antilia.infomaresme.Module;
import com.antilia.infomaresme.data.dao.interfaces.IItemsDao;
import com.antilia.infomaresme.data.dataobjects.Category;
import com.antilia.infomaresme.data.dataobjects.Item;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.SortDirection;

/**
 * @author Ernesto
 *
 */
public class GaeItemsDao implements IItemsDao {

	/**
	 * 
	 */
	public GaeItemsDao() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void delete(Item o) {
		Module.getDatastoreService().delete(o.getId());
		
	}

	@Override
	public Item load(Key id) {
		try {
			return getItem(Module.getDatastoreService().get(id));
		} catch (EntityNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	public Item getItem(Entity entity) {
		try {
			Item item = new Item();
			BeanPopulator.populateBean(item, entity);
			return item;
		} catch (IntrospectionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	

	@Override
	public void save(Item o) {
		Entity entity = new Entity("Item");
		entity.setProperty("title", o.getTitle());
		entity.setProperty("description", o.getDescription());
		entity.setProperty("categoryPath", o.getCategoryPath());
		entity.setProperty("category1", o.getCategory1());
		entity.setProperty("category2", o.getCategory2());
		entity.setProperty("category3", o.getCategory3());
		entity.setProperty("category4", o.getCategory4());
		entity.setProperty("category5", o.getCategory5());
		entity.setProperty("category6", o.getCategory6());		
		entity.setProperty("price", o.getPrice());
		entity.setProperty("categoryTitle", o.getCategoryTitle());
		entity.setProperty("geographicPath", o.getGeographicPath());
		entity.setProperty("geographicLocation", o.getGeographicLocation());
				
		
		Module.getDatastoreService().put(entity);		
		o.setId(entity.getKey());
	}

	@Override
	public List<Item> findAll() {
		Query query = new Query(Item.class.getSimpleName());
		List<Entity>  entities = Module.getDatastoreService().prepare(query).asList(
				FetchOptions.Builder.withDefaults()/*.limit(size).offset(start)*/);
		List<Item> items = new ArrayList<Item>();
		for(Entity entity: entities) {
			Item item= getItem(entity);
			if(item != null) {
				items.add(item);
			}
		}
		return items;
	}

	@Override
	public int countAll() {
		Query query = new Query(Item.class.getSimpleName());
		return Module.getDatastoreService().prepare(query).countEntities(
				FetchOptions.Builder.withDefaults());
	}

	@Override
	public List<Item> getItems(Category category, Category place, int start,
			int size, SortParam sortParam) {
		Query query = new Query(Item.class.getSimpleName());
		if(category!=null) {
			int depth = category.getDepth();
			Category parent = category;
			while (parent != null) {
				switch(depth) {
				 	case 1: {
				 		query.addFilter("category1", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 2: {
				 		query.addFilter("category2", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 3: {
				 		query.addFilter("category3", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 4: {
				 		query.addFilter("category4", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 5: {
				 		query.addFilter("category5", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 6: {
				 		query.addFilter("category6", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				}
				parent = parent.getParent();
				depth--;
			}
		}
		if(sortParam != null) {
			query.addSort(sortParam.getProperty(), sortParam.isAscending()?SortDirection.ASCENDING:SortDirection.DESCENDING);
		}
		if(place != null) {
			String s = Item.buildCategory(place);
			query.addFilter("geographicPath", FilterOperator.EQUAL, s);
		}
		List<Entity>  entities = Module.getDatastoreService().prepare(query).asList(
				FetchOptions.Builder.withDefaults().limit(size).offset(start));
		List<Item> items = new ArrayList<Item>();
		for(Entity entity: entities) {
			Item item= getItem(entity);
			if(item != null) {
				items.add(item);
			}
		}
		return items;
	}

	@Override
	public Long countItems(Category category, Category place) {
		Query query = new Query(Item.class.getSimpleName());
		if(category!=null) {
			int depth = category.getDepth();
			Category parent = category;
			while (parent != null) {
				switch(depth) {
				 	case 1: {
				 		query.addFilter("category1", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 2: {
				 		query.addFilter("category2", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 3: {
				 		query.addFilter("category3", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 4: {
				 		query.addFilter("category4", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 5: {
				 		query.addFilter("category5", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				 	case 6: {
				 		query.addFilter("category6", FilterOperator.EQUAL, parent.getId());
				 		break;
				 	}
				}
				parent = parent.getParent();
				depth--;
			}
		}
		if(place != null) {
			String s = Item.buildCategory(place);
			query.addFilter("geographicPath", FilterOperator.EQUAL, s);
		}
		return new Long(Module.getDatastoreService().prepare(query).countEntities(
				FetchOptions.Builder.withDefaults()));
	}



}
